package system_unlock

import (
	"go_server/game_server/api/service"
	"go_server/game_server/api/service/build"
	"go_server/game_server/constants"
	"go_server/game_server/dao/system_unlock_dao"
	"go_server/game_server/dataconfig/config_manager"
	"go_server/game_server/event_manager"
	"go_server/game_server/event_manager/event_data"
	"go_server/game_server/event_manager/event_data/event_impl"
	"go_server/game_server/initializer/map_data_init"
	"go_server/game_server/protocol/pb"
	"go_server/zinx/zlog"
	"gorm.io/datatypes"
	"slices"
)

type systemUnlockService struct {
	service.AbsService
	eventMethods map[event_data.EventType]func(event event_data.IEvent)
}

var serverObj *systemUnlockService

func Init() {
	serverObj = &systemUnlockService{
		eventMethods: make(map[event_data.EventType]func(event event_data.IEvent)),
	}
	event_manager.EventManagerObj.AddServiceEvent(event_data.LoginEvent, onSystemUnlockLoginEvent, serverObj)
	event_manager.EventManagerObj.AddServiceEvent(event_data.BuildLevelupEvent,
		onSystemUnlockBuildLevelupEvent, serverObj)
	event_manager.EventManagerObj.AddServiceEvent(event_data.UpStarHeroEvent, onSystemUnlockHeroStarEvent, serverObj)
	event_manager.EventManagerObj.AddServiceEvent(event_data.BuildUnlockEvent, onSystemUnlockBuildUnlockEvent, serverObj)
}

func onSystemUnlockBuildUnlockEvent(event event_data.IEvent) {
	roleId, ok := event.GetRoleId()
	if !ok {
		return
	}

	unlockEvent := event.(*event_impl.BuildUnlockEvent)
	buildMaps := unlockEvent.BuildMaps

	buildLvMap := config_manager.GetTableUnlockSheetUnlockByBuildLv()
	systemUnlock := system_unlock_dao.GetSystemUnlockByKey(roleId)
	var retArr []int32
	bChange := false
	for cfgBuildId, levels := range buildMaps {
		tempMap, ok := buildLvMap[cfgBuildId]
		if !ok {
			continue
		}

		for unlockId, condition := range tempMap {
			if slices.Max(levels) < condition {
				continue
			}
			if systemUnlock == nil {
				systemUnlock = new(system_unlock_dao.SystemUnlock)
				systemUnlock.RoleId = roleId
				systemUnlock.Counter = datatypes.NewJSONType(make(map[int32]int32))
				systemUnlock.UnlockArr = make([]byte, constants.SYSTEM_CELL_UNLOCK)
			}
			if systemUnlock.UnlockArr[unlockId-1] == 1 {
				continue
			}
			systemUnlock.UnlockArr[unlockId-1] = 1
			retArr = append(retArr, unlockId)
			bChange = true
		}
	}

	if len(retArr) > 0 {
		retMsg := &pb.UnlockUpdateS2C{UnlockArr: retArr}
		unlockEvent.RoleConn.SendBuffPBMsg(uint32(pb.ProtocolManager_UnlockUpdate), retMsg)
	}

	if bChange {
		system_unlock_dao.NewOrUpdateSystemUnlock(systemUnlock)
	}
}

func onSystemUnlockHeroStarEvent(event event_data.IEvent) {
	heroStarEvent := event.(*event_impl.UpStarHeroEvent)
	roleId, ok := event.GetRoleId()
	if !ok {
		return
	}
	heroStar := heroStarEvent.AfterStar
	heroStarMap := config_manager.GetTableUnlockSheetUnlockByHeroStar()
	unlockArr, ok := heroStarMap[heroStar]
	if !ok {
		return
	}

	var retArr []int32
	bChange := false
	systemUnlock := system_unlock_dao.GetSystemUnlockByKey(roleId)
	for _, unlockId := range unlockArr {
		if systemUnlock == nil {
			systemUnlock = new(system_unlock_dao.SystemUnlock)
			systemUnlock.RoleId = roleId
			systemUnlock.Counter = datatypes.NewJSONType(make(map[int32]int32))
			systemUnlock.UnlockArr = make([]byte, constants.SYSTEM_CELL_UNLOCK)
		}
		if systemUnlock.UnlockArr[unlockId-1] == 1 {
			continue
		}
		systemUnlock.UnlockArr[unlockId-1] = 1
		retArr = append(retArr, unlockId)
		bChange = true
	}

	if len(retArr) > 0 {
		retMsg := &pb.UnlockUpdateS2C{UnlockArr: retArr}
		heroStarEvent.RoleConn.SendBuffPBMsg(uint32(pb.ProtocolManager_UnlockUpdate), retMsg)
	}

	if bChange {
		system_unlock_dao.NewOrUpdateSystemUnlock(systemUnlock)
	}
}

func onSystemUnlockBuildLevelupEvent(event event_data.IEvent) {
	buildLevelupEvent := event.(*event_impl.BuildLevelupEvent)
	roleId, ok := event.GetRoleId()
	if !ok {
		return
	}
	level := buildLevelupEvent.Level
	buildConfigId := buildLevelupEvent.CfgBuildId

	buildLvMap := config_manager.GetTableUnlockSheetUnlockByBuildLv()
	tempMap, ok := buildLvMap[buildConfigId]
	if !ok {
		return
	}

	var retArr []int32
	bChange := false
	systemUnlock := system_unlock_dao.GetSystemUnlockByKey(roleId)
	for unlockId, condition := range tempMap {
		if level < condition {
			continue
		}
		if systemUnlock == nil {
			systemUnlock = new(system_unlock_dao.SystemUnlock)
			systemUnlock.RoleId = roleId
			systemUnlock.Counter = datatypes.NewJSONType(make(map[int32]int32))
			systemUnlock.UnlockArr = make([]byte, constants.SYSTEM_CELL_UNLOCK)
		}
		if systemUnlock.UnlockArr[unlockId-1] == 1 {
			continue
		}
		systemUnlock.UnlockArr[unlockId-1] = 1
		retArr = append(retArr, unlockId)
		bChange = true
	}

	if len(retArr) > 0 {
		retMsg := &pb.UnlockUpdateS2C{UnlockArr: retArr}
		buildLevelupEvent.RoleConn.SendBuffPBMsg(uint32(pb.ProtocolManager_UnlockUpdate), retMsg)
	}

	if bChange {
		system_unlock_dao.NewOrUpdateSystemUnlock(systemUnlock)
	}
}

func onSystemUnlockLoginEvent(event event_data.IEvent) {
	loginEvent := event.(*event_impl.RoleLoginEvent)
	conn := loginEvent.RoleConn
	nRoleId, ok := event.GetRoleId()
	if !ok {
		return
	}

	buildLvMap := config_manager.GetTableUnlockSheetUnlockByBuildLv()
	systemUnlockData := system_unlock_dao.GetSystemUnlockByKey(nRoleId)
	if systemUnlockData == nil {
		systemUnlockData = new(system_unlock_dao.SystemUnlock)
		systemUnlockData.RoleId = nRoleId
		systemUnlockData.Counter = datatypes.NewJSONType(make(map[int32]int32))
		systemUnlockData.UnlockArr = make([]byte, constants.SYSTEM_CELL_UNLOCK)
		defer system_unlock_dao.NewOrUpdateSystemUnlock(systemUnlockData)
		for buildCfgId, tempMap := range buildLvMap {
			maxLevel := build.GetBuildMaxLv(nRoleId, map_data_init.InitMapID, buildCfgId)
			for unlockId, condition := range tempMap {
				if condition > maxLevel {
					continue
				}

				systemUnlockData.UnlockArr[unlockId-1] = 1
			}
		}
	}


	if len(systemUnlockData.UnlockArr) > 0 {
		retMsg := new(pb.SystemUnlockS2C)
		for i, v := range systemUnlockData.UnlockArr {
			if v != 0 {
				retMsg.UnlockArr = append(retMsg.UnlockArr, int32(i) + 1)
			}
		}

		conn.SendBuffPBMsg(uint32(pb.ProtocolManager_SystemUnlock), retMsg)
	}
}

func (s *systemUnlockService) GetModuleName() string {
	return "system_unlock"
}

func (s *systemUnlockService) GetEventHandleFunc(eventType event_data.EventType) (func(event event_data.IEvent), bool) {
	eventFunc, ok := s.eventMethods[eventType]
	if !ok {
		zlog.Errorf("GetEventHandleFunc Err!!! method not found!!! eventType: %d", eventType)
		return nil, false
	}
	return eventFunc, true
}

func (s *systemUnlockService) GetEventMap() map[event_data.EventType]func(event event_data.IEvent) {
	return s.eventMethods
}
